﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using com.ubosi.spider.config;
using com.ubosi.spider.core.Net;

namespace com.ubosi.spider.hotel.HotelComment
{
    /// <summary>
    /// 抓取17U网站上点评实现类
    /// </summary>
    public class Spider17UHotelComment: BaseSpider,ISpiderHotelComment
    {       
        public Spider17UHotelComment(core.Net.NetSpider netSpider, spider.config.SpiderConfig spiderConfig)
            : base(netSpider, spiderConfig)
        {
        }

        /// <summary>
        /// 解析HTML,从中抓取点评数据
        /// </summary>
        /// <param name="htmlData"></param>
        /// <param name="spiderHotelCommentConfig"></param>
        /// <param name="startDate"></param>
        /// <param name="endDate"></param>
        /// <returns></returns>
        private List<com.ubosi.model.Entity.HotelComment> ParseHtmlData(string htmlData, spider.config.SpiderHotelCommentConfig spiderHotelCommentConfig)
        {
            List<com.ubosi.model.Entity.HotelComment> list = new List<com.ubosi.model.Entity.HotelComment>();

            if (string.IsNullOrEmpty(htmlData))
            {
                return list;
            }

            RegxConfig regxConfig = new RegxConfig(spiderHotelCommentConfig.CommentListRegx.Substring(1,3));
            MatchCollection mc = Regex.Matches(htmlData, spiderHotelCommentConfig.CommentListRegx.Substring(5));
            
            foreach (Match match in mc)
            {
                string CommentItemText = match.Groups[0].Value;

                com.ubosi.model.Entity.HotelComment hotelComment = new com.ubosi.model.Entity.HotelComment();
                
                hotelComment.Author = SingleMatch(CommentItemText, spiderHotelCommentConfig.AuthorRegx,string.Empty);
                hotelComment.CommentDate = DateTime.Parse(SingleMatch(CommentItemText,spiderHotelCommentConfig.CommentDateRegx, DateTime.Now.ToString("yyyy-MM-dd")));
                hotelComment.FacilitiesScore = getScore(SingleMatch(CommentItemText, spiderHotelCommentConfig.FacilitiesScoreRegx, "0.0"));
                hotelComment.PriceScore = getScore(SingleMatch(CommentItemText, spiderHotelCommentConfig.PriceScoreRegx, "0.0"));
                hotelComment.ServiceScore = getScore(SingleMatch(CommentItemText, spiderHotelCommentConfig.ServiceScoreRegx, "0.0"));
                hotelComment.TrafficScore = getScore(SingleMatch(CommentItemText, spiderHotelCommentConfig.TrafficScoreRegx, "0.0"));
                hotelComment.IsGood = string.IsNullOrEmpty(SingleMatch(CommentItemText, spiderHotelCommentConfig.IsGoodRegx, string.Empty)) ? (short)0 : (short)1;
                if (hotelComment.IsGood == 0)
                {
                    hotelComment.IsGood = string.IsNullOrEmpty(SingleMatch(CommentItemText, spiderHotelCommentConfig.IsBadRegx, string.Empty)) ? (short)0 : (short)-1;
                }
                hotelComment.CommentStatus = (short)0;
                hotelComment.CommentText = SingleMatch(CommentItemText, spiderHotelCommentConfig.CommentTextRegx, string.Empty);
                if (!string.IsNullOrEmpty(hotelComment.CommentText))
                {
                    list.Add(hotelComment);
                }
            }
            return list;
        }

        /// <summary>
        /// 单个值匹配
        /// </summary>
        /// <param name="s"></param>
        /// <param name="regx"></param>
        /// <returns></returns>
        private string SingleMatch(string s, string regx,string defaultValue)
        {
            try
            {
                RegxConfig regxConfig = new RegxConfig(regx.Substring(1, 3));
                MatchCollection mc = Regex.Matches(s, regx.Substring(5));
                if (mc.Count > 0 && mc[0].Success)
                {
                    string value = mc[0].Result("$" + regxConfig.Position.ToString());
                    return value;
                }
                else
                {
                    return defaultValue;
                }
            }
            catch
            {
                return defaultValue;
            }
        }

        private float getScore(string score)
        {
            try
            {
                return float.Parse(score);
            }
            catch
            {
                return (float)0;
            }
        }

        #region ISpiderHotelComment 成员
        /// <summary>
        /// 抓取指定日期时间段内的酒店点评
        /// </summary>        
        /// <param name="hotelId">来源酒店ID</param>
        /// <param name="startDate">开始日期</param>
        /// <param name="endDate">结束日期</param>
        /// <returns></returns>
        public List<com.ubosi.model.Entity.HotelComment> SpiderHotelComment(string hotelId, DateTime startDate, DateTime endDate)
        {
            if (_NetSpider == null || _SpiderConfig == null)
            {
                throw new SpiderHotelCommentException("抓取蜘蛛未初始化！");
            }

            List<com.ubosi.model.Entity.HotelComment> listAll = new List<com.ubosi.model.Entity.HotelComment>();

            spider.config.SpiderHotelCommentConfig spiderHotelCommentConfig = _SpiderConfig.GetSpiderCommentConfig("17u");
            
            //抓第一页
            string url = string.Format(spiderHotelCommentConfig.SpiderUrl, hotelId, spiderHotelCommentConfig.PageNo);            
            string htmlData = GetHtmlDocument(url, NetSpider.GetEncoding(spiderHotelCommentConfig.Encoding));

            int PageCount = int.Parse(SingleMatch(htmlData, spiderHotelCommentConfig.PageCountRegx, "1"));
            
            for (int i = spiderHotelCommentConfig.PageNo; i <= PageCount;i++)
            {
                //抓地二页
                if (i > spiderHotelCommentConfig.PageNo)
                {
                    url = string.Format(spiderHotelCommentConfig.SpiderUrl, hotelId, i);
                    htmlData = GetHtmlDocument(url, NetSpider.GetEncoding(spiderHotelCommentConfig.Encoding));
                    //抓取失败,跳过该页继续抓下一页
                    if (string.IsNullOrEmpty(htmlData))
                    {
                        continue;
                    }
                }

                //解析每一页的数据，返回改页点评列表
                List<com.ubosi.model.Entity.HotelComment> pageList = ParseHtmlData(htmlData, spiderHotelCommentConfig);

                bool isFinish = false;
                
                foreach (com.ubosi.model.Entity.HotelComment hotelComment in pageList)
                {
                    //点评位于时间段内
                    if (hotelComment.CommentDate <= endDate && hotelComment.CommentDate >= startDate)
                    {
                        hotelComment.SrcId = spiderHotelCommentConfig.SourceId;
                        hotelComment.HotelId = hotelId;//来源酒店ID
                        listAll.Add(hotelComment);
                    }
                    else
                    {
                        //点评不位于时间段内则表示抓取完成，不再继续
                        isFinish = true;
                        break;
                    }
                    if (isFinish)
                    {
                        break;
                    }
                }                
            }
            //返回符合条件的点评结果
            return listAll;
        }

        #endregion
    }
    /// <summary>
    /// 点评抓取异常类
    /// </summary>
    public class SpiderHotelCommentException : Exception
    {
        public SpiderHotelCommentException(string message)
            : base(message)
        {
        }
    }
}
